﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Text;
using System.Threading;

namespace WindowService
{
    public class ComHelper
    {
        
        private SerialPort _Comm = new SerialPort();
        private StringBuilder _Builder = new StringBuilder();//避免在事件处理方法中反复的创建，定义到外面。
        private long _ReceivedCount = 0;//接收计数
        private int _TimeOut = 30000;
        
        //窗体初始化
        public ComHelper(string portName, int baudRate = 9600, int timeOut = 30000)
        {
            //初始化SerialPort对象
            _Comm.NewLine = "\r\n";
            _Comm.RtsEnable = true;//根据实际情况吧。

            //添加事件注册
            _Comm.DataReceived += new SerialDataReceivedEventHandler(comm_DataReceived);
            //关闭时点击，则设置好端口，波特率后打开
            _Comm.PortName = portName;
            _Comm.BaudRate = baudRate;
            this._TimeOut = timeOut;
            this.open();
        }

        private bool open()
        {
            string portName = _Comm.PortName;
            int baudRate = _Comm.BaudRate;

            //根据当前串口对象，来判断操作
            if (!_Comm.IsOpen)
            {
                try
                {
                    _Comm.Open();
                    Log.WriteLog("CommHelper Opened SerialPort PortName:" + portName + " BaudRate:" + baudRate, LogType.Trace);
                }
                catch (Exception ex)
                {
                    //捕获到异常信息，创建一个新的comm对象，之前的不能用了。
                    _Comm = new SerialPort();
                    //现实异常信息给客户。
                    Log.WriteLog("CommHelper Open SerialPort PortName:" + portName + " BaudRate:" + baudRate + " failed, error:" + ex.Message, LogType.Trace);
                    return false;
                }
            }
            else
            {
                Log.WriteLog("CommHelper SerialPort was Opened, PortName:" + portName + " BaudRate:" + baudRate, LogType.Trace);
            }
            return true;
        }

        private void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = _Comm.BytesToRead;//先记录下来，避免某种原因，人为的原因，操作几次之间时间长，缓存不一致
            byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
            _ReceivedCount += n;//增加接收计数
            _Comm.Read(buf, 0, n);//读取缓冲数据

            //直接按ASCII规则转换成字符串
            _Builder.Append(Encoding.ASCII.GetString(buf));

            Log.WriteLog("CommHelper Receive Message From PortName:" + _Comm.PortName + " BaudRate:" + _Comm.BaudRate + " Content:" + Encoding.ASCII.GetString(buf), LogType.Trace);
        }

        public string SendCommand(string command)
        {
            if (!this.open())
            {
                return "";
            }
            _Builder.Remove(0, _Builder.Length);
            _Comm.WriteLine(command);
            Log.WriteLog("CommHelper Send Message To PortName:" + _Comm.PortName + " BaudRate:" + _Comm.BaudRate + " Send Content:" + command, LogType.Info);
            int timeOut = this._TimeOut;
            string receive = "";
            while (
                _Builder.Length == 0 || !(_Builder.ToString().Contains("OK") || _Builder.ToString().Contains("+CME ERROR:")))
            {
                Thread.Sleep(100);
                timeOut -= 100;
                //Log.WriteLog("CommHelper Receive Message TimeOut: " + timeOut + " Message:" + _Builder.ToString(), LogType.Info);
                if (timeOut <= 0)
                {
                    _Builder.Append(_Comm.NewLine + "+CME ERROR: Time Out" + _Comm.NewLine);
                    break;
                }
            }
            receive = _Builder.ToString();
            Log.WriteLog("CommHelper Receive Message From PortName:" + _Comm.PortName + " BaudRate:" + _Comm.BaudRate + " Reci Content:" + receive, LogType.Info);
            return receive;
        }

    }
}
